#include "bsp_flash.h"
#include "bsp_math.h"

typedef union
{
	uint8_t buff[4];
	uint32_t data;
}uFlashData;

uint8_t FlashBspWrite(uint32_t addr,uint8_t* write_buff,uint16_t write_len)
{
	uint8_t ret = 0;
	uint16_t i = 0u,j = 0u;
	uint32_t write_addr = addr;
	uFlashData write_data;

	if(write_addr >= FLASH_ADDR_MAX)
	{
		return 1u;
	}else{}
	
	while((write_addr%4) != 0)	//找到Word边界编程地址
	{
		write_addr -= 1;
		i++;
	}
	
	if(i)	//非Word边界编程地址
	{
		write_data.data = *((uint32_t *)(write_addr));
		MathBspStrCopy(&write_data.buff[i],write_buff,4 - i);
		if(FL_PASS != FL_FLASH_Program_Word(FLASH,write_addr,write_data.data))
		{
			return 2;
		}else{}
		write_addr += 4u;
		j = 4 - i;
	}else{}
	
	while(j < write_len)
	{
		i = 0;
		write_data.data = *((uint32_t *)(write_addr));//将flash数据读出
		while(j < write_len)
		{
			if(i >= 4u)
			{
				break;
			}
			else
			{
				write_data.buff[i++] = write_buff[j++];
			}
		}
		
		if(FL_PASS != FL_FLASH_Program_Word(FLASH,write_addr,write_data.data))
		{
			return 3;
		}
		else
		{
			write_addr += 4u;
		}
	}
	
	return ret;
}

uint8_t FlashBspRead(uint32_t addr,uint8_t* read_buff,uint16_t read_len)
{
	uint8_t ret = 0;
	uint16_t i = 0u,j = 0u;
	uFlashData read_data;
	uint32_t read_addr = addr;
	
	// 参数合法性检查
	if(addr >= FLASH_ADDR_MAX || read_buff == NULL || read_len == 0)
	{
		return 1u;
	}
		
	while(read_addr%4)	//找到被4整除的地址
	{
		read_addr -= 1;
		i++;
	}
	
	if(i)
	{
		read_data.data = *((uint32_t *)(read_addr));
		MathBspStrCopy(read_buff,&read_data.buff[i],4-i);
		j = 4-i;
		read_addr += 4u;
	}else{}
	
	while(j < read_len)
	{
		i = 0;
		read_data.data = *((uint32_t *)(read_addr));//将flash数据读出
		read_addr += 4u;
		while(j < read_len)
		{
			if(i >= 4u)
			{
				break;
			}
			else
			{
				read_buff[j++] = read_data.buff[i++];
			}
		}
	}
	
	return ret;
}

uint8_t FlashBspErase(uint32_t addr)
{
	uint8_t ret = 0;
	
	if(addr >= FLASH_ADDR_MAX)
	{
		return 1u;
	}
	else if(addr % FLASH_PAGE_SIZE)
	{
		return 2u;
	}else{}
	
	if(FL_PASS == FL_FLASH_PageErase(FLASH,addr))
	{
		ret = 0;
	}
	else
	{
		ret = 3u;
	}
		
	return ret;
}
